package com.bbm.communitysystem.service.impl;

import com.bbm.communitysystem.core.redis.RoleRedis;
import com.bbm.communitysystem.domain.Role;
import com.bbm.communitysystem.domain.bo.RoleBo;
import com.bbm.communitysystem.domain.dto.role.RoleDto;
import com.bbm.communitysystem.mapper.RoleMapper;
import com.bbm.communitysystem.service.IRoleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author bbm
 * @since 2025-02-13
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {

    private final RoleRedis roleRedis;

    private final PerServiceImpl perService;

    private final RouterServiceImpl routerService;

    @Override
    public int addRole(RoleDto role) {

        Role role1 = new Role();

        role1.setRoleName(role.getName());
        role1.setRouterIds(role.getRouter());
        role1.setRolePerId(role.getPer());
        role1.setStatus(0 + "");
        role1.setUpdateBy(role.getUpdateBy());
        role1.setUpdateTime(System.currentTimeMillis() + "");
        role1.setRoleDescription(role.getRoleDescription());

        boolean save = save(role1);

        log.info("添加角色：{}", role1);

        if (!save) {
            return 1;
        }

        roleRedis.setRole(role1.getId() + "", role1);

        return 0;
    }

    @Override
    public int putRole(RoleDto roleDto) {
        boolean update = lambdaUpdate()
                .set(!roleDto.getName().isEmpty(), Role::getRoleName, roleDto.getName())
                .set(!roleDto.getRouter().isEmpty(), Role::getRouterIds, roleDto.getRouter())
                .set(!roleDto.getPer().isEmpty(), Role::getRolePerId, roleDto.getPer())
                .set(roleDto.getStatus() != null, Role::getStatus, roleDto.getStatus())
                .set(!roleDto.getRoleDescription().isEmpty(),Role::getRoleDescription, roleDto.getRoleDescription())

                .set(Role::getUpdateTime, System.currentTimeMillis() + "")
                .set(Role::getUpdateBy, roleDto.getUpdateBy())
                .eq(Role::getId, roleDto.getId())
                .update();

        if (!update) {
            return 1;
        }
        log.info("修改角色：{}", roleDto);
        roleRedis.setRole(roleDto.getId() + "", getById(roleDto.getId()));

        return 0;
    }

    @Override
    public int delRole(Integer id) {

        if (removeById(id)) {
            roleRedis.setRole(id + "", null);

            log.info("删除角色：{}", id);

            return 0;
        }

        return 1;
    }

    @Override
    public RoleDto getRole(Integer id) {
        Role role = roleRedis.getRole(id + "");

        if (role == null) {
            return null;
        }
        RoleDto roleDto = new RoleDto();
        roleDto.setId(role.getId());
        roleDto.setName(role.getRoleName());
        roleDto.setRouter(role.getRouterIds());
        roleDto.setPer(role.getRolePerId());
        roleDto.setStatus(role.getStatus());
        roleDto.setUpdateBy(role.getUpdateBy());

        roleDto.setPerId(perService.getPerList(roleDto.getPerIndex()));
        roleDto.setRouterId(routerService.getRouterList(roleDto.getRouterIndex()));

        return roleDto;
    }

    @Override
    public RoleDto[] getRoleList(Integer[] ids) {

        RoleDto[] roleDtos = new RoleDto[ids.length];
        for (int i = 0; i < ids.length; i++) {
            roleDtos[i] = getRole(ids[i]);
        }

        return roleDtos;
    }

    @Override
    public RoleDto getRole(Role role) {

        RoleDto roleDto = new RoleDto();


        roleDto.setId(role.getId());
        roleDto.setName(role.getRoleName());
        roleDto.setStatus(role.getStatus());
        roleDto.setRouter(role.getRouterIds());
        roleDto.setPer(role.getRolePerId());
        roleDto.setUpdateBy(role.getUpdateBy());

        roleDto.setPerId(perService.getPerList(roleDto.getPerIndex()));
        roleDto.setRouterId(routerService.getRouterList(roleDto.getRouterIndex()));

        return roleDto;
    }

    @Override
    public RoleDto[] getRoleList(Role[] roles) {
        RoleDto[] roleDtos = new RoleDto[roles.length];

        for (int i = 0; i < roles.length; i++) {
            roleDtos[i] = getRole(roles[i]);
        }

        return roleDtos;
    }


    /**
     *  删除权限业务
     *  业务描述：
     *      go学长触犯了我，所以他的三号权限被我删除了，
     *      但是没删除角色和权限的关联索引，所以导致权限被删除了
     *      ，角色的权限索引却还在。现在我要删除角色和权限的关联索引。
     *  业务逻辑实现
     *      拿到要删除的权限id，查询拥有该权限索引的角色。
     *      拿到角色，修改该角色的权限索引，删除该权限。
     *
     *  修改逻辑：
     *      声明一个数组。
     *      遍历拥有该权限索引的角色数组。
     *      遍历该角色的权限索引数组。
     *      如果该权限索引等于要删除的权限索引，则跳过。
     *      如果该权限索引不等于要删除的权限索引，则添加到数组中。
     *      遍历结束将新的数组赋值给角色的权限索引。
     *      最后将角色的权限索引更新到数据库中。
     *      删除数据库中的权限信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int delPer(RoleBo roleBo) {

        for (Integer perId : roleBo.getPerId()) {

            log.info("删除权限：{}", perId);

            List<Role> list = lambdaQuery()
                    .like(Role::getRolePerId, perId)
                    .list();

            list.forEach(role -> {
                log.info("角色ID：{},移除角色{}的{}权限", role.getId(), role.getRoleName(), perId);
                String[] perIds = role.getRolePerId().split(",");
                String[] newPerIds = new String[perIds.length - roleBo.getPerId().length];
                int j = 0;
                for (String id : perIds) {
                    if (id.equals(perId + "")) {
                        continue;
                    }
                    newPerIds[j] = id;
                    j++;
                }


                role.setRolePerId(String.join(",", newPerIds));
                boolean b1 = updateById(role);

                if (!b1) {
                    throw new RuntimeException("删除角色和权限的关联索引失败");
                }



            });

            boolean b = perService.removeById(perId);
            if (!b) {
                throw new RuntimeException("删除权限失败");
            }
        }

        return 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int delRouter(RoleBo roleBo) {
        for (Integer routerId : roleBo.getRouterId()) {
            log.info("删除路由：{}", routerId);
            List<Role> list = lambdaQuery()
                    .like(Role::getRouterIds, routerId)
                    .list();
            list.forEach(role -> {
                log.info("角色ID：{},移除角色{}的路由{}", role.getId(), role.getRoleName(), routerId);
                String[] routerIds = role.getRouterIds().split(",");
                String[] newRouterIds = new String[routerIds.length - roleBo.getRouterId().length];
                int j = 0;
                for (String id : routerIds) {
                    if (id.equals(routerId + "")) {
                        continue;
                    }
                    newRouterIds[j] = id;
                    j++;
                }


                role.setRouterIds(String.join(",", newRouterIds));
                boolean b = updateById(role);
                if (!b) {
                    throw new RuntimeException("删除角色和路由的关联索引失败");
                }
            });

            if (!routerService.removeById(routerId)) {
                throw new RuntimeException("删除路由失败");
            }
        }
        return 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int delPerRouter(RoleBo roleBo) {

        delPer(roleBo);

        delRouter(roleBo);

        return 0;
    }


}
